#ifndef PUDGE_UI_HPP
#define PUDGE_UI_HPP

#include <pudge/meta/lazy.hpp>
#include <vector>

namespace pudge { namespace ui {

	/// A widget is simply a structure wrapping two functions.
	///
	///	widget::draw() returns a function composite in the form of
	///	void (game_context&)
	///
	/// widget::tick() returns a function composite in the form of
	/// void (game_context&,frame&)
	///
	/// Users add new functions to the composite by passing the += operator
	/// a copy of a parameterized functor with a compatible signature.
	/// 
	/// For example:
	///
	/// struct draw_function { template<class C> void operator()(C&) { // do something }};
	/// widget_instance.draw() += draw_function(//constructor);
	///
	/// Now call the draw function
	///
	/// widget_instance.draw()(draw_context(//constructor));

	template<class Traits> struct widget
	{
		typedef typename Traits::game_context_type game_context_type;
		typedef typename Traits::ui_frame_type frame_type;
 		
		struct tick_base
		{
			virtual ~tick_base(){}
			virtual void tick(game_context_type &, frame_type &) = 0;
		};
		struct draw_base
		{
			virtual ~draw_base(){}
			virtual void draw(game_context_type &) = 0;
		};
		template<class F> struct tick_function : tick_base
		{
			F function_;
			tick_function(F & f) : function_(f) {}
			virtual ~tick_function(){}
			virtual void tick(game_context_type & c, frame_type & f)
			{
				function_(c,f);
			}
		};
		template<class F> struct draw_function : draw_base
		{
			F function_;
			draw_function(F & f) : function_(f){}
			virtual ~draw_function(){}
			virtual void draw(game_context_type & c)
			{
				function_(c);
			}
		};
		struct draw_composite : std::vector<draw_base*>
		{
			~draw_composite()
			{
				for(iterator i = begin(); i != end(); ++i)
					delete *i;
			}
			template<class F> draw_composite & operator += (F & f)
			{
				push_back(new draw_function<F>(f));
				return *this;
			}
			void operator ()(game_context_type & c)
			{
				for(iterator i = begin(); i != end(); ++i)
					(*i)->draw(c);
			}
		};
		struct tick_composite : std::vector<tick_base*>
		{
			~tick_composite()
			{
				for(iterator i = begin(); i != end(); ++i)
					delete *i;
			}
			template<class F> tick_composite & operator += (F & f)
			{
				push_back(new tick_function<F>(f));
				return *this;
			}
			void operator ()(game_context_type & c, frame_type & f)
			{
				for(iterator i = begin(); i != end(); ++i)
					(*i)->tick(c,f);
			}
		};

		draw_composite draw_;
		tick_composite tick_;

		draw_composite & draw() { return draw_; }
		tick_composite & tick() { return tick_; }

		virtual ~widget() {}
	};

	template<class Traits> struct widget_group : widget<Traits>
	{
		typedef widget<Traits> widget_type;
		typedef std::vector<widget<Traits>*> widget_list;

		virtual ~widget_group() {}

		widget_list widgets_;
		widget_list & widgets() { return widgets_; }
	};

	using pudge::meta::deref;

	struct tick_widget_group_
	{
		template<class C, class F, class G> struct result { typedef void type; }; 
		template<class C, class F, class G> void operator()(C & ucon, F & frame_, G & group_) const
		{
			typedef G::widget_list W;
			typedef W::iterator I;
			W & w = group_.widgets();
			for(I i = w.begin(); i != w.end(); ++i)
				(*i)->tick()(ucon,frame_);
			return 0

		}		
	};

	pudge::meta::lazy<tick_widget_group_> const tick_widget_group = tick_widget_group_();

	struct draw_widget_group_
	{
		template<class C, class G> struct result { typedef void type; }; 
		template<class C, class G> void operator()(C & ucon, G & group_) const
		{
			typedef G::widget_list W;
			typedef W::iterator I;
			W & w = group_.widgets();
			for(I i = w.begin(); i != w.end(); ++i)
				(*i)->draw()(ucon);
			return ucon;
		}		
	};

	pudge::meta::lazy<draw_widget_group_> const draw_widget_group = draw_widget_group_();
}}

#endif